import { reactive, Ref } from "vue";
import { useDrag } from "/@/hooks/useDrag";
import type { CompDataItem, ConfigurationInstance, Connection, ToggleSelectData } from "/@/components/types";
import type { SvgInfo, BoxSelect } from "/@/Configuration/types";

interface UseSelectOptions {
  connection: Connection;
  compInstance: { [key: string]: ConfigurationInstance<CompDataItem> };
  onMousedown: (e: MouseEvent) => void;
  getSvgInfo: () => SvgInfo | undefined;
  isEditor: Ref<boolean>;
}

export function useSelect({ connection, compInstance, onMousedown, getSvgInfo, isEditor }: UseSelectOptions) {
  /**
   * 选择
   */
  const curSelectData: ToggleSelectData[] = reactive([]);
  function getSelectedIndex(toggleSelData: ToggleSelectData) {
    for (let i = 0; i < curSelectData.length; i++) {
      const el = curSelectData[i];
      if (el.type === toggleSelData.type && el.index === toggleSelData.index) {
        return i;
      }
    }
    return false;
  }
  function resetSelect(exceptIndex?) {
    for (let i = curSelectData.length - 1; i >= 0; i--) {
      if (exceptIndex === i) continue;
      const el = curSelectData[i];
      el.unSelect && el.unSelect();
      curSelectData.splice(i, 1);
    }
  }
  function toggleSelect(toggleSelData: ToggleSelectData) {
    const selIndex = getSelectedIndex(toggleSelData);
    if (toggleSelData.selected) {
      if (!toggleSelData.multiple) {
        resetSelect(selIndex);
      }
      if (selIndex === false) {
        curSelectData.push(toggleSelData);
      }
    } else {
      if (selIndex !== false) {
        curSelectData.splice(selIndex, 1);
      }
    }
  }
  /**
   * 框选
   */
  const boxSelect = reactive<BoxSelect>({
    x: -1,
    y: -1,
    width: 0,
    height: 0,
  });
  let exceptRectIds: string[] = [];
  const { dragStart } = useDrag<[], { startTarget: HTMLElement }>({
    unStopPropagation: !isEditor.value,
    getRelativeElement() {
      const info = getSvgInfo() as SvgInfo;
      return info.container;
    },
    start(startData, e) {
      boxSelect.width = 0;
      boxSelect.height = 0;
      boxSelect.x = startData.x;
      boxSelect.y = startData.y;
      onMousedown(e);
      return {
        startTarget: e.target as HTMLElement,
      };
    },
    move({ dx, dy, offsetX, offsetY, startData }) {
      if (isEditor.value) {
        if (dx < 0) {
          boxSelect.x = offsetX;
        } else {
          boxSelect.x = startData.x;
        }
        if (dy < 0) {
          boxSelect.y = offsetY;
        } else {
          boxSelect.y = startData.y;
        }
        boxSelect.width = Math.abs(dx);
        boxSelect.height = Math.abs(dy);
      }
    },
    end({ isClick, startResult }) {
      if (isClick) {
        //点击事件
        if (startResult.startTarget.getAttribute("data-configuration")) {
          resetSelect();
        }
      } else if (isEditor.value) {
        // const seletedEls: string[] = [];
        let hasReset = false;
        for (const i in compInstance) {
          const ins = compInstance[i];
          if (ins && ins.isInBoxSelect) {
            if (ins.isInBoxSelect(boxSelect)) {
              if (!hasReset) {
                hasReset = true;
                resetSelect();
              }
              ins.select();
            }
          }
        }

        exceptRectIds = [];
        curSelectData.forEach((el) => {
          if (el.getPipePathInfo) {
            const points = el.getPipePathInfo().points;
            points.forEach((p) => {
              const drags = connection.getConnect(p.id);
              if (drags && drags.length > 0) {
                //路径点只能连接一个设备
                const index = curSelectData.findIndex((el) => el.id === drags[0].id);
                if (index >= 0) {
                  exceptRectIds.push(p.id);
                }
              }
            });
          }
        });
      }
      boxSelect.width = 0;
      boxSelect.height = 0;
    },
  });
  //框选后 组合拖拽
  const multipleSelect = {
    startTogether(id) {
      if (curSelectData.length < 2) {
        return false;
      }
      if (curSelectData.findIndex((el) => el.id === id) === -1) return false;
      curSelectData.forEach((el) => {
        let startData;
        if (el.drag && el.drag.start) {
          startData = el.drag.startData = el.drag.start();
        }
        if (startData && startData.pointIds) {
          //path在选择集合中
          startData.dragTogetherPoints.forEach((el) => {
            connection.startTogether(el.id, [...startData.pointIds, ...exceptRectIds]);
          });
        } else {
          connection.startTogether(el.id as string, [...exceptRectIds]);
        }
      });
      return true;
    },
    moveTogether(moveOptions) {
      curSelectData.forEach((el) => {
        if (el.drag) {
          moveOptions.startData = el.drag.startData;
          el.drag.move(moveOptions);
        }
        const startData = moveOptions.startData;
        if (startData && startData.pointIds) {
          startData.dragTogetherPoints.forEach((el) => {
            connection.moveTogether(el.id, moveOptions, [...startData.pointIds, ...exceptRectIds]);
          });
        } else {
          connection.moveTogether(el.id as string, moveOptions, [...exceptRectIds]);
        }
      });
    },
    endTogether() {
      curSelectData.forEach((el) => {
        let startData;
        if (el.drag && el.drag.end) {
          el.drag.end();
          startData = el.drag.startData;
        }
        if (startData && startData.pointIds) {
          startData.dragTogetherPoints.forEach((el) => {
            connection.endTogether(el.id, [...startData.pointIds, ...exceptRectIds]);
          });
        } else {
          connection.endTogether(el.id as string, [...exceptRectIds]);
        }
      });
    },
  };
  return {
    boxSelect,
    toggleSelect,
    startSelect: dragStart,
    multipleSelect,
    curSelectData,
  };
}
